#!/usr/bin/perl -w

# This is thumbs.pl, part of Picture Bank.  thumbs.pl displays a table of
#+ thumbnail images if they are available, and tries to be flexible in the
#+ types of thumbnail it can find.  So far it supports a thumb(s)(nails) sub
#+ directory, or concurrent files with the prefix or suffix of th or tn.
#+ thumbs.pl needs to be called from search.pl

# Copyright (C) 2007 Alexis Phoenix

# url should look something like:
# thumbs.pl?map=test.map&gallery1=/path1/+/path2/&gallery2=/path3/+/path4/+/path5/&paths=/new1/+/new2/

$start=&time();

$sep=";"; # define separator as used for cgi query strings
$config_path="/usr/lib/cgi-bin/config/";
# $config_path="cgi-bin/config/";
#@identifiers=("th","tn","thumb");

# need to create an "any of" function

use CGI;

$query=new CGI;
$query->delete("Submit"); # new
$path_string=$query->param("paths") or undef $path_string;  # moved
$query->delete("paths");  # new
$map=$query->param("map"); # thumbs.pl doesn't use map itself, but passes it to pages.pl
$query->delete("map");
$gals=$query->query_string() or undef $gals; # whatever's left

if (defined($gals)) {
  @galleries=split("$sep",$query->query_string()); # needs to be in 2 parts with a variable? # new
  # should now have (":gallery-1=...",":gallery-2=...", etc)
}
else {
  @galleries=@gals=()
}

print <<HEAD;
content-type=text/html \n\n
<html><head><title>Thumbnail Viewer</title>
</head><body><H3>Welcome to the thumbnails page</H3>
HEAD

@gal_paths=();
if (scalar(@galleries)>0) { # at least one gallery # new block
  $g=1;
  foreach (@galleries) {
    @this_gal=split("=",$_);
    $this_gal[0]=~s/:gallery-//; # get rid of the colon/gallery/dash combo # will work?
    @tmp=split(" ",$this_gal[1]);
    @gal_paths=(@gal_paths,$this_gal[0],@tmp) # create alternation of names with path groups
  }
  $gals="Galleries: ".join(" ",@gal_paths)
}
else {
  @gal_paths=("No galleries to show\n");
  $g=0
}
# got rid of ugly broken code to separate galleries (below) and put this in (above)

print "Started at".$start;
print "galleries: ".join(" ",@gal_paths)."<br>\n";
#print "query string: $query_string <br>\n";
print "got params and galleries if any at".&time();


$p=0;
if (defined($path_string)) {
  $p=1;
  @paths=split/\s/,$path_string;
}
else {
  @paths=("Nothing to show for non-galleries");
  $path_string=""
}

if ($g==0&&$p==0) {  # moved block
  print "Nothing to display.  Quitting.</body></html>\n";
  exit
}

print "separated non-gals at".&time();

#foreach (@all) {
# deleted block of gallery getting code
#}


open (CONF,"$config_path/options.txt"); # simplistic conf file parsing...
foreach (<CONF>) {
  unless (m/\#/) {
    push(@config,$_)
  }
}
foreach (@config)
{
  if (m/table_columns/) {
    @line=split/\s+/,;
    $columns=$line[1] # number of columns in output table
  }
  if (m/default_image/) {
    @line=split/\s+/,;
    $default_image=$line[1]
  }
  if (m/thumb_default/) {
    @line=split/\s+/,;
    $thumb_default=$line[1]
  }
  if (m/default_thumb_size/) {
    @line=split/\s+/,;
    $default_thumb_size=$line[1]
  }
  if (m/thumb_method/) {
    @line=split/\s+/,;
    $thumb_method=$line[1]
  }
  if (m/thumb_max_height/) {
    @line=split/\s+/,;
    $thumbs_max_height=$line[1]
  }
  if (m/thumb_min_height/) {
    @line=split/\s+/,;
    $thumbs_min_height=$line[1]
  }
  if (m/thumb_max_width/) {
    @line=split/\s+/,;
    $thumbs_max_width=$line[1]
  }
  if (m/thumb_min_width/) {
    @line=split/\s+/,;
    $thumbs_min_width=$line[1]
  }
}
close(CONF);
print "<img align=right src=$thumb_default>\n";

#if (defined(@gal_paths)) {
# moved code to gallery separation
#}

print "Currently viewing: @gals <br>non-galleries: $path_string</p>\n".
"done parsing config file at".&time()."<br>\n";


print <<NAV; # temp until include set up
<table border=1><th colspan=2>Go to:</th><tr><td>
<a href=admin.pl>Admin page</a></td>
<td><a href=search.pl>Search page</a></td></tr>
</table>
NAV


if ($g==1) {
  foreach (@gal_paths) {
    if (m/\//) {
      print "<td colspan=$columns>Path is $_<td>"; # should appear below gallery name
      &table_maker($_);
      print "</table>";
      print "<br>"
    }
    else {
      print "<table border=1><th colspan=$columns>Gallery: $_</th>\n"
    }
  }
}

print "\n\n"; # for easier checking of output
print "<br>Finished printing galleries at".&time()."<br>\n";
print "<p>End gallery section";

if ($p==1) {
  print ", start of non-gallery results\n";
  foreach (@paths) {
    print "<table border=1>";
    &table_maker($_);
    print "</table>";
    print "<br>"
  }
}
else {
  print "</p>@paths\n"
}

print "\n\n"; # for easier checking of output
print "Finished printing non-galleries at".&time()."<br>\n";

print "</body></html>";
  
sub table_maker($) {
print "<tr colspan=$columns><td>table maker started at".&time()."</tr></td>\n";
  my $end=0;
  my $tend=0; 
  @files=();
  @thumbs=();
  my $path=$thumbs_path=$_[0];
  chomp $path;
#  print "tn path $path";
  opendir (PATH, $path);
  my @contents=readdir(PATH);
  closedir (PATH);
  foreach (@contents) {
    if (!-d "$path/$_" && m/^tn/||m/^thumb/||m/^th/||m/tn\./||m/thumb\./||m/th\./) {
      push(@thumbs, "$thumbs_path"."/"."$_")      
    }
    elsif (-d && m/thumb/) {
      $thumbs_path+="/$_";
      opendir (TN, $thumbs_path);
      @thumbs=readdir(TN);
      closedir(TN)
    }
    else {
      unless (-d "$path/$_") {
        push(@files, $_)
      }  # end unless
    } # end else
  } # end foreach
 # print "Thumbnails we have: @thumbs <br>Files we have: @files <br>\n";
 @thumbs=sort(@thumbs);
 @files=sort(@files);
print "<tr colspan=$columns><td>created thumbs array containing<br>\n".join(", ",@thumbs).
"<br>\nand files array containing<br>\n".join(", ",@files)."<br>\nat".&time()."</tr></td>\n";

  $end=$#files;
  if (scalar(@thumbs)>0) {
    $tend=$#thumbs;
  }
  else {
    $thumbs[0]="noThumbs"
  }
  if ($end != $tend) {
  print "<tr colspan=$columns><td>(1) started thumbs/files mismatch at ".&time()."</td></tr>\n";
    use Image::Magick;
    print "thumbs 0 is $thumbs[0]<br>\n";
    print "files 0 is $files[0]<br>\n";
    unless ($thumbs[0] eq "noThumbs") {
      my $sample = new Image::Magick;      # should be able to use Ping for these
      $status = $sample->Read("$path/$files[0]");  #+ rather than open the files
      if ($status != 0) {
        print "could not get sample file size: error $status"
      }
      $fwidth = $sample->Get("columns");        # changed fsample and tsample to sample
 print "fwidth: $fwidth<br>\n";
  #    undef($fsample);                       #+ save creation/destruction of an object.
  #    my $sample=new Image::Magick;
      $status = $sample->Read("$thumbs_path/$thumbs[0]");
      if ($status != 0) {
        print "could not get sample thumbnail size: error $status"
      }
      $twidth = $sample->Get("columns");
      undef($sample); # don't need these taking memory anymore
      $ratio=printf(($twidth/$fwidth),2); # need to do sane rounding here eg to two dp.
      print "<tr colspan=$columns><td>(2) got ratio for thumbs size: $ratio at ".&time()."</td></tr>\n";

     &miscount ($end,$tend,$path,$ratio,@files) # function to try to sort out missing/extra thumbs
    }
    else {
      &miscount ($end,$tend,$path,"none",@files)
    }
      
  }

  print "<tr><td colspan=$columns>$path</td></tr>\n";

  if (defined($map)) {
    $map_string="map=$map&"
  }
  else {
    $map_string=""
  }
#print "map string is $map_string";
  my $index=0;
  while ($index<=$end) {
    print "<tr>";
      for (1..$columns) {
        if ($index<=$end) {
          $file="$path/$files[$index]";
          unless (exists $message[$index]) {
            $message[$index]=""
          }
          $thumb="$thumbs[$index]"; # assumes thumbs concurrent with files
    #      print "my thumb is $thumb";
          print "<td><a href=pages.pl?"."$map_string"."path=$file>$message[$index]\n";
          print "<img src=\"$thumb\" alt=\"Cannot display thumb\"></img></a></td>\n";
          $message="";
          $index++
        }
        else {
          print "<td></td>";
        }
      }
      print "</tr>";
  }
print "<tr colspan=$columns><td>table maker finished at".&time()."</tr></td>\n";
}



sub miscount {
print "<tr colspan=$columns><td>miscount started at".&time()."</tr></td>\n";
  my $end=shift(@_);
  my $tend=shift(@_);
  my $path=shift(@_);
  my $ratio=shift(@_);
  my @files=@_;
  my $flag=0;
##################
# start section to sort out thumb naming convention

  if ($end>$tend) { # in this case there's a thumb missing
    $i=$end;
    $flag=1;

  # code to get existing thumbs size moved to table_maker
  
    @parts=split/\./,$thumbs[0];  # need to get filename sans extension
    $ext=$parts[$#parts];
    if ($thumbs[0]=~m/((^tn[\W_]*)|(^th[\W_]*)|(^tn[\W_]*)|(^thumb[\W_]*))/) {
      @pattern=($1,"fore")
    }  # pick up prefix thumbnail identifier
    elsif ($#parts<2 && $parts[0]=~m/([^a-zA-Z0-9]th$)/||$parts[0]=~m/([^a-zA-Z0-9]tn$)/||$parts[0]=~m/([^a-zA-Z0-9]thumb$)/) {
      @pattern=($1,"back")
    }  # pick up suffix thumbnail identifier
    elsif (not $path eq $thumbs_path) { # prevent overwrites as name is the same
      @pattern=("none","none") # assumed in this case to be a separate thumbs dir
    } # end else (elsif)
    else { # there are no thumbnails presumably or they are identified non-standardly
 #   if (scalar(@thumbs)==0) {
      $thumbs_path="$path"."/PB_thumbs"; # no existing thumbs found in this case
      mkdir($thumbs_path);
      @parts=split/\./,$files[0];  # can't get from an existing thumb, use a file instead
      $ext=$parts[$#parts];
      @pattern=("none","none") # no pattern needed as going in a separate directory
    } # end if..else inner
  } # end if outer
#############
# end section  
  else {  # there's an extra thumb
    $i=$tend;
    $flag=0
  }  
  print "done sorting pattern out at".&time()."</tr></td>\n";  
  for (0..$i) {
    if ($#thumbs == $#files){
      return  # job is done, leave the subroutine
    }
    $message[$_]="";
    @file=split/\./,$files[$_]; # get just the first part of the filename
    $fname=$file[0];
    if ($flag==1) { # a thumb must be missing
      if (defined ($thumbs[$_])) {
        if ($thumbs[$_]!~/$fname/) {
          splice (@thumbs,$_,0,"$thumb_default"); # default substitute image in case 
                                                  #+ makethumb fails
          $thumbs[$_]=&makethumb($path,$files[$_],$fname,$thumbs_path,@pattern,$ext,$ratio);
        }
      }
    #  }
    }
    elsif ($flag==0) {  # a file must be missing
                         #+ it needs to go in after the last one checked
      splice (@files,$_,0, "$default_image"); # check syntax
      $message[$_]="The file to match $thumbs[$_] is missing"
    }
    else {
      next
    }
  }
print "<tr colspan=$columns><td>miscount finished at".&time()."</tr></td>\n";
 }
#}


sub makethumb {
print "<tr colspan=$columns><td>makethumb started at".&time()."</tr></td>\n";
  my $path=shift(@_);
  my $file="$path"."/".shift(@_);
  my $fname=shift(@_);
  my $thumbs_path=shift(@_);
  my $format=shift(@_);
  my $position=shift(@_);
  my $ext=shift(@_);
  my $ratio=shift(@_);

# routine to generate thumbs according to config
  my $img = new Image::Magick;
  $status=$img->Read($file);
  print "reading file: $file\n";
  if ($status!=0) {
    $message="could not read file error: $status"
  }

# start geometry section (untested)
# geometry is w x h or %.  Complexity added due to max/min limits
  if ($thumb_method eq "default"||$ratio eq "none") {
    $geom="$default_thumb_size"
  }
  elsif ($thumb_method eq "width") {
    $w=$img->Get('columns'); # get the width of the file being worked on
    $w=$w*$ratio;
    if ($w>$thumbs_max_width) {
      $w=$thumbs_max_width
    }
    if ($w<$thumbs_min_width) {
      $w=$thumbs_min_width
    }
    $geom="w=".printf($w,2)
  }
  elsif ($thumb_method eq "height") {
    $r=$img->Get('rows');
    $r=($r*$ratio);
    if ($r>$thumbs_max_height) {
      $r=$thumbs_max_height
    }
    if ($r<$thumbs_min_height) {
      $r=$thumbs_min_height
    }
    $geom="r=".printf($r,2)
  }
  elsif ($thumb_method eq "percent") {
    $geom=($ratio*100)."%"
  }
print "geometry is $geom";
  $status = $img->Resize(geometry=>$geom);
  if ($status) {
    print "Failed resize.  Error: $status"
  }
############################################
# end geometry section

# create a filename according to pattern
  if ($position eq "fore") {
    $tname="$format"."$fname"."\."."$ext"
  }
  elsif ($position eq "back") {
    $tname="$fname"."$format"."\."."$ext"
  }  
  else {
    $tname="$fname"."\."."$ext"
  }
  my $thumbnail="$thumbs_path"."/"."$tname";
#print "i would write: $thumbnail\n";
  $status=$img->Write("$thumbnail");  # write out an actual thumnail image to disk

  if ($status) {
    $message="$message"."could not write thumbnail error: $status"
  }
  return $thumbnail
print "<tr colspan=$columns><td>makethumb finished at".&time()."</tr></td>\n";
}



sub time() {
($second, $minute, $hour,,,,,,) = localtime();
my $time=" $hour:$minute:$second <br>\n";
return $time
}
